#include<iostream>
#include<string>
#include<functional>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<cstring>
#include<pthread.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<memory>

#include"InetAddr.hpp"
#include"Log.hpp"
#include"Socket.hpp"

using namespace socket_ns;
class TcpServer;
using io_service_t = std::function<void (socket_sptr,InetAddr client)>;

class ThreadData
{
    public:
        ThreadData(socket_sptr fd,InetAddr addr,TcpServer *s)
        :sockfd(fd)
        ,clientaddr(addr)
        ,self(s)
        {}
    public:
    socket_sptr sockfd;
    InetAddr clientaddr;
    TcpServer *self;
};
class TcpServer
{
    public:
    TcpServer(int port,io_service_t service)
    :_localaddr("0",port),
    _listensock(std::make_unique<TcpSocket>()),
    _service(service),
    _isrunning(false)
    {
        _listensock->BuildListenSocket(_localaddr);
    }
    static void *HandlerSock(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData*>(args);
        td->self->_service(td->sockfd,td->clientaddr);
        ::close(td->sockfd->SockFd());//关闭
        delete td;
        return nullptr;
    }
    void loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            InetAddr peeraddr;
            socket_sptr normalsock = _listensock->Accpter(&peeraddr);
            if(normalsock==nullptr)
            continue;
            pthread_t t;
            ThreadData *td = new ThreadData(normalsock,peeraddr,this);
            pthread_create(&t,nullptr,HandlerSock,td);//线程分离
        }
        _isrunning = false;
    }
    ~TcpServer()
    {}
    private:
        InetAddr _localaddr;
        std::unique_ptr<Socket>_listensock;
        bool _isrunning;
        io_service_t _service;
};